package ae.pcfc.cldos.online.web.controller.base;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.context.MessageSource;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import ae.pcfc.cldos.online.common.clddb.domain.AttachmentType;
import ae.pcfc.cldos.online.common.delegate.AdminTaskDelegate;
import ae.pcfc.cldos.online.common.delegate.EncryptionDelegate;
import ae.pcfc.cldos.online.common.exception.BadAppException;
import ae.pcfc.cldos.online.common.vo.FileVO;
import ae.pcfc.cldos.online.common.vo.UserVO;
import ae.pcfc.cldos.online.web.ViewPath;
import ae.pcfc.cldos.online.web.exception.ResourceNotFoundException;
import ae.pcfc.cldos.online.web.model.FilesIncomingBean;
import ae.pcfc.cldos.online.web.services.breadcrumbs.BreadCrumbsFactoryService;
import ae.pcfc.cldos.online.web.services.request.beans.RequestVariablesBean;
import ae.pcfc.cldos.online.web.services.security.SecurityService;
import ae.pcfc.cldos.online.web.util.StringEscapeEditor;
import ae.pcfc.cldos.online.web.util.StringUtils;

/**
 * Base Controller for all controllers
 * @author ammar
 *
 */
/**
 * @author akhader
 *
 */
/**
 * 
 * @author arosa
 *
 */
public abstract class BaseController implements HandlerExceptionResolver{
	
	@Autowired
	protected SecurityService securityService;
	
	@Autowired
	@Qualifier("mapper")
	protected DozerBeanMapper mapper;
	
	@Autowired(required=false)
	@Qualifier("requestVariablesBean")
	protected RequestVariablesBean requestVariablesBean;
	
	@Value("${work.mode}")
	private String mode;
	
	@Value("${login.context.path}")
	private String loginPath;

	@Autowired(required=false)
	@Qualifier("encryptionDelegate")
	protected EncryptionDelegate encryptionDelegate;
	
	@Autowired(required=false)
	@Qualifier("adminTaskDelegate")
	protected AdminTaskDelegate adminTaskDelegate;

	@Autowired
	protected BreadCrumbsFactoryService breadCrumbsFactoryService;
	
	@Autowired
	protected MessageSource messageSource;
	
	protected DozerBeanMapper getMapper() {
		return mapper;
	}
	
	protected FileVO createFileVOFromMultipartFile(MultipartFile multipartFile, String typeCode) throws IOException{
		
		FileVO fileVO = new FileVO();
		fileVO.setAttachmentTypeCode(typeCode);
		fileVO.setInputStream(multipartFile.getInputStream());
		String fileOriginalName = multipartFile.getOriginalFilename();
		fileVO.setFileExt(StringUtils.getFileExtension(fileOriginalName));
		fileVO.setFileName(fileOriginalName);
		fileVO.setUploadDate(new Date());
		return fileVO;
	}
	
	protected List<FileVO> getFileVOList(FilesIncomingBean filesIncomingBean) throws IOException{
		MultipartFile passportCopy = filesIncomingBean.getPassportCopy() ;
		MultipartFile letterFromCompany = filesIncomingBean.getLetterFromCompany();
		MultipartFile photograph = filesIncomingBean.getPhotograph();
		
		MultipartFile insurancePaper = filesIncomingBean.getInsurancePaper();
		MultipartFile cancellationOrVisitCopy = filesIncomingBean.getCancellationOrVisitCopy();
		MultipartFile cancellationPaper = filesIncomingBean.getCancellationPaper();
		
		MultipartFile exitDocument = filesIncomingBean.getExitDocument();
		
		List<FileVO> fileVOList = new ArrayList<FileVO>();
		
		if(passportCopy!=null && !passportCopy.isEmpty()){
			fileVOList.add(createFileVOFromMultipartFile(passportCopy, AttachmentType.__ATTACHMENT_TYPE_PASSPORT));
		}
		if(letterFromCompany!=null && !letterFromCompany.isEmpty()){
			fileVOList.add(createFileVOFromMultipartFile(letterFromCompany, AttachmentType.__ATTACHMENT_TYPE_COMPANY_LETTER));
		}
		if(photograph!=null && !photograph.isEmpty()){
			fileVOList.add(createFileVOFromMultipartFile(photograph, AttachmentType.__ATTACHMENT_TYPE_PHOTO));
		}
		if(insurancePaper!=null && !insurancePaper.isEmpty()){
			fileVOList.add(createFileVOFromMultipartFile(insurancePaper, AttachmentType.__ATTACHMENT_TYPE_INSURRANCE_PAPER));
		}
		if(cancellationOrVisitCopy!=null && !cancellationOrVisitCopy.isEmpty()){
			fileVOList.add(createFileVOFromMultipartFile(cancellationOrVisitCopy, AttachmentType.__ATTACHMENT_TYPE_CANCELATION_OR_VISIT_PAPER));
		}
		if(cancellationPaper!=null && !cancellationPaper.isEmpty()){
			fileVOList.add(createFileVOFromMultipartFile(cancellationPaper, AttachmentType.__ATTACHMENT_TYPE_CANCELATION_PAPER));
		}
		if(exitDocument!=null && ! exitDocument.isEmpty()){
			fileVOList.add(createFileVOFromMultipartFile(exitDocument, AttachmentType.__ATTACHMENT_TYPE_EXIT_DOCUMENT));
		}
		
		return fileVOList;
	}
	
	protected UserVO getUserVO(){
		UserVO userVO = new UserVO();
		userVO.setUsername(securityService.getLoginedUsername());
		userVO.setEmployee(securityService.isCompanyEmployee());
		userVO.setAdmin(securityService.isCompanyAdmin());
		userVO.setGeneralAdmin(securityService.isGeneralAdmin());
		return userVO;
	}
	
	protected UserVO getGeneralUserVO(){
		UserVO userVO = new UserVO();
		userVO.setUsername("BackOfficeUser");
		userVO.setEmployee(false);
		userVO.setAdmin(false);
		userVO.setGeneralAdmin(true);
		return userVO;
	}
	
	@InitBinder
	protected void initBinder(WebDataBinder binder) throws Exception {
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
		dateFormat.setLenient(false);
		binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
		//binder.registerCustomEditor(String.class, new StringEscapeEditor(true, true, true));
	}
	
	@ModelAttribute
	public void populateAuthData(ModelMap model){
		if(securityService.isAuthenticated()){
			model.put("loginedUsername", securityService.getLoginedUsername());
			model.put("isCompanyAdmin", securityService.isCompanyAdmin());
			model.put("isCompanyEmployee", securityService.isCompanyEmployee());
		}
		model.put("mode", mode);
		model.put("loginPath", loginPath);
	}
	
	@ExceptionHandler({ResourceNotFoundException.class, BadAppException.class, MissingServletRequestParameterException.class})
	protected String handleInvalidRequestException(Throwable e){
		return ViewPath.__FORWARD+ViewPath.__NOT_FOUND;
	}
	
	@ExceptionHandler({FileNotFoundException.class})
	protected void handleInvalidRequestException(Throwable e, HttpServletResponse response) throws IOException{
		response.setStatus(HttpServletResponse.SC_NOT_FOUND);
		response.getWriter().print("");
		response.flushBuffer();
	}
	
	@ExceptionHandler({Throwable.class})
	protected void handleGeneralException(Throwable e, HttpServletResponse response,
			HttpServletRequest request) throws ServletException, IOException{
		
		e.printStackTrace();
		if(!requestVariablesBean.isAjaxRequest()){
			requestVariablesBean.setExceptionStore(e);
			String forwardTo = "/"+ViewPath.__ERROR;
			request.getRequestDispatcher(forwardTo).forward(request, response);
		} else {
			response.setStatus(500);
			response.getWriter().print("ERROR 500");
		}
	}
	
	public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		
		if(ex instanceof MaxUploadSizeExceededException){
			Map<String, Object> model = new HashMap<String, Object>();
			MaxUploadSizeExceededException m = (MaxUploadSizeExceededException)ex;
			model.put("maxSize", m.getMaxUploadSize());
			return new ModelAndView("error.fileupload", model);
		} else {
			return new ModelAndView("error.generic");
		}
	}

}
